Hello,大家好
繼「不只是瀏覽器!JavaScript 征服世界的第一步 - Node.js」 這邊文章後
我們終於又要介紹到另一個讓我十分興奮的專案 - 「Babel」
就如同 Node.js,嘗試把 JavaScript 語法應用在任何 runtime 的一樣
如果你記得我們上次提到的「程式語言標準化」
就可以知道,標準化的代價其中之一
就是你會有許多不同版本的 runtime,讓開發者們為了支援性而痛苦
但是,Babel 這個專案
使得在 JavaScript 標準發展的同時
我們又可以寫出相容幾乎所有瀏覽器的 code
他是怎麼做到的,背後有什麼故事?
就在接下來介紹!
前面提到過,JavaScript 有許多不同的 runtime
像是在 ES6 新增的 arrow function 這個功能(2015年的標準)
如果我們上 Can I Use 搜尋
你可以看到,IE 以及少數手機瀏覽器
至今都還沒有完全支援
或是現在最新的 async
await
語法
是在 2016
年才推出的標準
對於瀏覽器開發商來說
要馬上支援,不會是一件簡單的事情
但是,就算有了標準,也要有人實作,有人用才有意義
這也就是 Babel 解決的問題
Babel 專案最早的開發者叫做 Sebastian
基本上,在 ES6 剛出來,還沒有任何瀏覽器支援的時候
有幾個 Google 的工程師寫個一個套件,叫做「Traceur」
基本上就是 ES6 -> ES5 的程式碼轉換器
他的概念很簡單,就是把像是 const
let
這些還沒支援的語法
編譯成瀏覽器看的懂的版本
他最早在高中維護的專案叫做 6to5
基本上就是把 ES6
轉成 ES5
Sebastian 的故事滿激勵人心的,基本上是講一個 17 歲高中生
因為開源專案的力量走出原本澳洲家鄉的故事
基本上這就是 Babel 這個專案本身在做的事情了
他會把 ES6, ES7, ES8, ES100 的語法都編譯成你要的版本
Babel 的功用基本上就是轉換 JavaScript 的程式碼
基本上身為一個編譯器,你很直接地可以想到他有三個轉換的階段
預設 Babel 其實是沒有任何功能的,他只會產生 abstract syntax tree,接下來編譯出一模一漾的 code
他會需要安裝各種「套件」,才能就影響第二步,transform
這個階段
當然,你可以自幹一套編譯規則來用
不過,在 Babel 裡,Preset 代表著已經被人定義好的 config
像是我今天可以自己出版 babel-preset-alxtz
我會把 for 迴圈
全部編譯成 goto
Babel 本身官方有維護一些 Official Presets
像是 es2015
es2016
es2017
這些是代表把當年 ECMAScript 定稿的功能實作出來
像是這是 es2015
這個 preset 使用的所有轉換規則
他把當年定稿的 arrow function
for of
spread
都盡可能轉換成可通用的 JavaScript 語法
(不過這邊有個小問題,我很好奇能不能讓 Babel 不要轉換成最簡單的版本,可不可以 ES7 轉 ES6 就好)
而像是 env
這個 preset
則是根據環境變數來設定要編譯到哪個程度
像是跟我們前幾天介紹的 browserlist
搭配
或是指定 node 的版本
不帶任何參數的話,會使用 babel-preset-latest
的設定
也就是 babel 現在實作到所有最新的功能都編譯
而像是 preset-react
preset-flow
就是拿來專門編譯 jsx
或 flow
程式碼的
(雖然我不確定跟 jsx-loader 比起來會用哪種)
有些 preset 我們會叫他 stage
這代表著,這些 preset 太新了
甚至還不在 ESXXX 之內
因為像是 ECMAScript 的提案,決定過程中
他們會有不同階段的提案
從 stage 0 開始
stage - 0
還沒被開會時討論過,以及只被部分拒絕的提案stage - 1
已經討論過,並且有如何實作的提案stage - 2
有精確定義的語法了,並且有實驗性的實作出來stage - 3
API 跟實作詳細,等待使用者的回應stage - 4
代表該功能/提案完全被接受,會加進當年度的 ES 裡
Babel 會盡量去更新現在有哪些提案
並且去實作他,放進相對應的 stage 裡
相較於 preset 這一整包
transform plugin 就是詳細定義的轉換規則了
像是 const
-> var
() => {}
-> function(){}
前面我們提到的 preset ,主要都是包含一些比較通用
瀏覽器不同標準的轉譯
但是,你當然也可以有各種情境,來轉換各種規則的程式碼
這些就是最基本的 Plugin
這就是 Babel 基本的故事了
https://babeljs.io/blog/2016/12/07/the-state-of-babel
想加入 babeljs 的 slack 討論可以發 issue 申請加入
https://github.com/babel/notes/issues/38
對了,babel 的英文意思是巴別塔
本身帶著「想解決語言不合」這個問題的用意